//implement QtTimerImpl
//andycai_sc 2011-05-29

#include "GParallel/GQt/QtTimerImpl.h"

//-------------------------------implement QtCommonTimerImpl--------------------------

QtCommonTimerImpl::QtCommonTimerImpl(GTimer *timer, QObject *parent) : QObject(parent),
GTimerImpl(timer)
{
    connect(&m_qTimer, SIGNAL(timeout()), SLOT(runTask()));
}

QtCommonTimerImpl::~QtCommonTimerImpl()
{
}

void QtCommonTimerImpl::beginImpl(long millisc)
{
    m_qTimer.start(millisc);
}

void QtCommonTimerImpl::cancelImpl()
{
    m_qTimer.stop();
}

void QtCommonTimerImpl::runTask()
{
    exec();
}

//------------------------------implement QtThreadTimerImpl-----------------------------

QtThreadTimerImpl::QtThreadTimerImpl(GTimer* gtimer, QObject *parent) : QObject(parent),
GTimerImpl(gtimer), m_timerThrRef(TimerThread::instance())
{
    if (!m_timerThrRef.isRunning())
    {
        m_timerThrRef.start();
        TaskContainer* container = m_timerThrRef.getTaskContainer();
        while ((container = m_timerThrRef.getTaskContainer()) == 0)
            m_timerThrRef.mSleep(10);
        connect(&m_timerThrRef, SIGNAL(newTimer(GTimerImpl*)),
                container, SLOT(addTimer(GTimerImpl*)), Qt::BlockingQueuedConnection);
    }
    m_timerThrRef.appendTimer(this);
    m_timerTask = m_timerThrRef.getTimerTask(this);
}

QtThreadTimerImpl::~QtThreadTimerImpl()
{
    cancelImpl();
    m_timerThrRef.deleteTimer(this);
}

void QtThreadTimerImpl::beginImpl(long millisc)
{
    m_timerTask->start(millisc);
}

void QtThreadTimerImpl::cancelImpl()
{
    m_timerTask->stop();
}

//------------------------TimerTask use to execute timer schedule----------------------

TimerTask::TimerTask(GTimerImpl *timerImpl, QObject *parent) : QObject(parent),
    m_timerImpl(timerImpl)
{
    connect(&m_timer, SIGNAL(timeout()), SLOT(task()));
    connect(this, SIGNAL(begin(int)), &m_timer, SLOT(start(int)), Qt::BlockingQueuedConnection);
    connect(this, SIGNAL(end()), &m_timer, SLOT(stop()), Qt::BlockingQueuedConnection);
}

void TimerTask::start(long mseconds)
{
    emit begin(mseconds);
}

void TimerTask::stop()
{
    emit end();
}

void TimerTask::task()
{
    m_timerImpl->exec();
}

TaskContainer::TaskContainer(QObject *parent) : QObject(parent)
{
}

TimerTask* TaskContainer::getTimerTask(GTimerImpl *timerImpl)
{
    m_taskMutex.lock();
    TimerTask* task = m_timerTasks.value(timerImpl);
    m_taskMutex.unlock();
    return task;
}

void TaskContainer::removeTimer(GTimerImpl *timerImpl)
{
    m_taskMutex.lock();
    m_timerTasks.remove(timerImpl);
    m_taskMutex.unlock();
}

bool TaskContainer::isEmpty() const
{
    return m_timerTasks.isEmpty();
}

void TaskContainer::addTimer(GTimerImpl *timerImpl)
{
    TimerTask* task = new TimerTask(timerImpl, this);
    m_taskMutex.lock();
    m_timerTasks.insert(timerImpl, task);
    m_taskMutex.unlock();
}

TimerThread TimerThread::_timerThread;

TimerThread::TimerThread(QObject *parent) : QThread(parent)
{
    m_taskContainer = 0;
}

TimerThread& TimerThread::instance()
{
    return _timerThread;
}

TimerTask* TimerThread::getTimerTask(GTimerImpl *timerImpl)
{
    return m_taskContainer->getTimerTask(timerImpl);
}

TaskContainer* TimerThread::getTaskContainer()
{
    return m_taskContainer;
}

void TimerThread::deleteTimer(GTimerImpl *timerImpl)
{
    m_taskContainer->removeTimer(timerImpl);
    if (m_taskContainer->isEmpty())
        quit();
}

void TimerThread::mSleep(unsigned long msec)
{
    QThread::msleep(msec);
}

void TimerThread::appendTimer(GTimerImpl *threadTimer)
{
    emit newTimer(threadTimer);
}

void TimerThread::run()
{
    m_taskContainer = new TaskContainer;
    exec();
}

//----------------------------implement createTimerFromQt-------------------------------------

GTimerImpl* createTimerFromQt(GTimer *timer)
{
#if defined(USE_QT_THREADTIMER)
    return new QtThreadTimerImpl(timer);
#else
    return new QtCommonTimerImpl(timer);
#endif
}
